//
//	RenSurface.h
//	Class for managing texture data as it flies around GPUrrs Elvis.
//	2006 John Wiggins
//
// This program is free software; you can redistribute it and/or modify  
// it under the terms of the GNU General Public License as published by  
// the Free Software Foundation; either version 2 of the License, or     
// (at your option) any later version.                                   
// 
// This program is distributed in the hope that it will be useful,       
// but WITHOUT ANY WARRANTY; without even the implied warranty of        
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         
// GNU General Public License for more details.                          
//     
//     You should have received a copy of the GNU General Public License     
//     along with this program; if not, write to the                         
//         Free Software Foundation, Inc.,                                       
//         59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.  
//-------------------------------------------------------------
#ifndef REN_SURFACE_H
#define REN_SURFACE_H
//-------------------------------------------------------------
#include <pthread.h>
#include <GL/gl.h>
//-------------------------------------------------------------
enum RenColorFormat
{
	GE_FMT_GRAY, // GL_LUMINANCE, 8-bit grayscale
	GE_FMT_YUV422, // GL_LUMINANCE_ALPHA, YUV 4:2:2 packed, common(?) output for video codecs
	GE_FMT_RGB, // GL_RGB, 24-bit RGB color
	GE_FMT_RGBA, // GL_RGBA, 32-bit RGBA color
};
//-------------------------------------------------------------
class RenSurface 
{
public:
                        RenSurface                      ( RenColorFormat fmt,
                                                            unsigned int width,
                                                            unsigned int height );
                        RenSurface                      ( RenSurface const & copy);
                        ~RenSurface                     ();

    unsigned char *     getData                         ();
    GLuint              getTextureHandle                () const;
    unsigned int        getDataSize                     () const;
    unsigned int        getDataSize                     ( RenColorFormat fmt,
                                                            unsigned int width,
                                                            unsigned int height ) const;

    void                modifyAttributes                ( RenColorFormat fmt,
                                                            unsigned int width,
                                                            unsigned int height );

    bool                operator==                      ( RenSurface const & surf ) const;
    bool                operator!=                      ( RenSurface const & surf) const;

    bool                lock                            ();
    void                unlock                          ();

    void                attachToFrameBuffer             ();
    void                detachFromFrameBuffer           ();
    int                 uploadToGPU                     ();
    int                 downloadFromGPU                 ();
    bool                isGPUResident                   () const;
    void                removeFromGPUWithoutDownload    ();

    unsigned int        height                          () const;
    unsigned int        width                           () const;

    RenColorFormat      colorFormat                     () const;
    GLint               textureIntFormat                () const;
    GLenum              textureFormat                   () const;
    
private:
    
    void                initPBO                         ();
    void                cleanupPBO                      ();
    void                initFBO                         ();
    void                cleanupFBO                      ();

    unsigned char *     mData;
    unsigned int        mWidth;
    unsigned int        mHeight;
    RenColorFormat      mFormat;
    pthread_mutex_t     mLock;

    GLuint              mPixelBuffer; // the pixel buffer object (for transfers)
    GLuint              mFrameBuffer; // the frame buffer object (for RTT)
    GLuint              mTexture; // the texture handle

    bool                mPBOAllocated;
    bool                mFBOAllocated;
    bool                mIsGPUResident;
    bool                mAttrModified;
};
//-------------------------------------------------------------
GLuint
RenSurface::getTextureHandle() const
{
    return mTexture;
}
//-------------------------------------------------------------
bool
RenSurface::operator==( RenSurface const & surf ) const
{
    return ( ( surf.mFormat == this->mFormat )
          && ( surf.mHeight == this->mHeight )
          && ( surf.mWidth == this->mWidth ) );
}
//-------------------------------------------------------------
bool
RenSurface::operator!=( RenSurface const & surf) const
{
    return !( surf == *this );
}
//-------------------------------------------------------------
bool
RenSurface::isGPUResident() const
{
    return mIsGPUResident;
}
//-------------------------------------------------------------
void
RenSurface::removeFromGPUWithoutDownload()
{
    mIsGPUResident = false;
}
//-------------------------------------------------------------
unsigned int
RenSurface::height() const
{
    return mHeight;
}
//-------------------------------------------------------------
unsigned int
RenSurface::width() const
{
    return mWidth;
}
//-------------------------------------------------------------
RenColorFormat
RenSurface::colorFormat() const
{
    return mFormat;
}
//-------------------------------------------------------------
#endif // REN_SURFACE_H
//-------------------------------------------------------------
